﻿package {
	import flash.display.Stage;
	import flash.display.MovieClip;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;
	import com.greensock.TweenMax;
	import com.greensock.easing.Strong;
	import com.greensock.easing.Quad;
	import flash.geom.Point;
	
	public class Flicking {
		private var stg:Stage;
		private var target:MovieClip;
		private var listMc:MovieClip;
		
		private var TOP:int;
		private var BOTTOM:int;
		// 리스트가 보여지는 영역 BOTTOM - TOP
		private var CONT_H:int;
		
		// 스크롤바 사용여부
		private var scrollFlag:Boolean;
		// 스크롤바 
		private var sc:MovieClip;
		// 스크롤바 크기
		private var scSize:Number;
		
		private var yArr:Array;
		private var prvY:Number;
		
		public function Flicking( _stg:Stage, _listMc:MovieClip, _mask_mc:MovieClip, _top:int, _bottom:int ) {
			// constructor code
			
			stg = _stg;
			listMc = _listMc;
			target = _mask_mc;
			TOP = _top;
			BOTTOM = _bottom;
			CONT_H = _mask_mc.height;
			listMc.mask = _mask_mc;
			
			//스크롤바 사용여부
			scrollFlag = false;
			// 플리킹 여부를 판단
			if( listMc.height > CONT_H ) {
				listMc.addEventListener( MouseEvent.MOUSE_DOWN, MOUSE_DOWN );
			}
		}
		
		public function init():void {
			listMc.y = 0;
			if ( scrollFlag ) sc.y = 0;
		}
		
		// MouseDown 시에 드래그 시작
		private function MOUSE_DOWN( e:MouseEvent ):void{
			prvY = getY(); //이전좌표
			yArr = [];
			
			// MouseUp 이벤트 등록
			stg.addEventListener( MouseEvent.MOUSE_UP, MOUSE_UP );
			listMc.addEventListener(MouseEvent.MOUSE_MOVE, MOUSE_MOVE );
			
			var rect:Rectangle = new Rectangle( listMc.x, -listMc.height, 0, listMc.height * 2 );
			listMc.startDrag( false, rect );
		}
		
		// MouseUp 시에 드래그 멈춤.
		private function MOUSE_UP( e:MouseEvent ):void{
			// MouseUp 이벤트 삭제.
			stg.removeEventListener( MouseEvent.MOUSE_UP, MOUSE_UP );
			listMc.removeEventListener(MouseEvent.MOUSE_MOVE, MOUSE_MOVE );
			listMc.stopDrag();
			
			// TOP, BOTTOM 을 확인해 제자리로 돌아감.
			if( listMc.y > TOP ) {
				moveTo( TOP );
			}else if( (listMc.y + listMc.height) < BOTTOM ) {
				moveTo( BOTTOM - listMc.height );
			}else{
				// 거리 (속도) 측정
				// 바로 이전에 움직였던 거리의 평균값을 파악
				var sum:Number = 0;
				var i:int;
				for( i = 0; i < 3; ++i ){
					if( yArr[i] ){
						sum += yArr[i];
					}else{
						sum += 0;
					}
				}
				//평균값에 10을 곱한만큼 이동
				sum = listMc.y + Math.floor( sum/3 ) * 10;
				
				moveTo_Check( sum );
			}
		}
		private function moveTo_Check( _targetY:Number ):void{
			TweenMax.to( listMc, .5, { y: _targetY, ease:Quad.easeOut( 10,10,10,1 ), onUpdate:scrollMoving, onComplete:tweenEnd } );
		}
		private function moveTo( _targetY:Number ):void{
			TweenMax.to( listMc, .5, { y: _targetY, ease:Quad.easeOut( 10,10,10,1 ), onUpdate:scrollMoving } );
		}
		
		
		private function MOUSE_MOVE( e:MouseEvent ):void {
			//TOP, BOTTOM을 벗어날경우 1:1이 아닌 조금 늘어지게 표현
			if( listMc.y > TOP ){
				listMc.y -= 2;
			}else if( listMc.y + listMc.height < BOTTOM ){
				listMc.y += 2;
			}
			
			// 이동한 거리를 차례로 배열에 저장
			if( yArr.length > 2 ) yArr.shift();
			var num:Number = getY() - prvY;
			yArr.push( num );
			
			//이전 좌표
			prvY = getY();
			
			//스크롤바 작동
			if ( scrollFlag ) {
				sc.visible = true; 
				setScrollPos();
			}
		}
		
		
		private function tweenEnd():void{
			//TOP, BOTTOM을 확인해서 제자리로 돌아감
			if( listMc.y > TOP ){
				moveTo( TOP );
			}else if( (listMc.y + listMc.height) < BOTTOM ) {
				moveTo( BOTTOM - listMc.height );
			}
		}
		
		private function getY():Number{
			var p:Point = listMc.localToGlobal( new Point( 0, listMc.mouseY ) );
			return p.y;
		}
		
		
		//스크롤바 추가
		public function addScroll( _sc:MovieClip ):Boolean{
			sc = _sc;
			sc.visible = false;
			scrollFlag = false;
			
			if( listMc.height > CONT_H ) {
				sc.visible = true;
			}
			
			if( sc.numChildren === 3 ){
				scrollFlag = true;
				//스크롤바 크기 계산.  ( 스크롤바 크기:영역 = 영역:리스트길이 )
				scSize = Number( CONT_H / listMc.height * CONT_H );
				setScrollPos();
			}
			return scrollFlag;
		}
		
		private function scrollMoving():void {
			if ( scrollFlag ) setScrollPos();
		}
		
		private function setScrollSize():void {
			var targetSize:Number = scSize;
			
			if( listMc.y > TOP ){  //TOP 넘어갈때
				//targetSize = scSize - TOP + sc.y;
				sc.y = TOP;
			}else if( listMc.y + listMc.height < BOTTOM ){  //BOTTOM 넘어갈때
				//targetSize = scSize - sc.y - sc.height + BOTTOM;
				sc.y = BOTTOM - targetSize;
			}
			
			//예외 처리
			if( targetSize < 4 ) targetSize = 4;
			targetSize = int( targetSize );
			
			sc.mid_mc.height = targetSize - sc.top_mc.height - sc.bottom_mc.height;
			sc.bottom_mc.y = sc.mid_mc.y + sc.mid_mc.height;
		}
		
		private function setScrollPos():void {
			sc.y = -( listMc.y * CONT_H / listMc.height );
			setScrollSize();
		}
		
	}
	
}
